import javax.microedition.lcdui.Graphics;
import javax.microedition.m3g.Background;
import javax.microedition.m3g.Camera;
import javax.microedition.m3g.Graphics3D;
import javax.microedition.m3g.Light;
import javax.microedition.m3g.Sprite3D;
import javax.microedition.m3g.Transform;

public class GameLayerManager {
    private final MyCanvas canvas;

    // scene geometry
    private int worldWidth = 0;     // world geometry , in general it is bigger that display
    private int worldHeight = 0;
    private float xOrigDisplay = 0;   // display origin position
    private float yOrigDisplay = 0;
    private float panScale = 0.2f;
    
    // states related data
    public final int STATE_IDLE = 0;           // for StateIdle class instance
    //TODO: add more states here
    public final int STATE_BOTTOMMARK = STATE_IDLE + 1;
    
    private State stateArr[] = new State[STATE_BOTTOMMARK];
    private State state = null;

    // OpenGL staff 
    private Graphics3D      iG3D;
    private Camera          iCamera;
    private Light           iLight;
    private Background      iBackground = new Background();
    
    private GameLayer[]     iLayerArr = new GameLayer[2];
        
    /**
     * Component initialization.
     */
    public GameLayerManager(MyCanvas aCanvas){
        canvas = aCanvas;
        
        worldHeight = canvas.DISP_HEIGHT * 2; // just for testing purposes
        worldWidth = canvas.DISP_WIDTH * 2;

        xOrigDisplay = 0;
        yOrigDisplay = 0;

        initStates();
        
        // get the singleton Graphics3D instance
        iG3D = Graphics3D.getInstance();

        // create a camera
        iCamera = new Camera();
        iCamera.setPerspective( 60.0f,              // field of view
            (float)canvas.DISP_WIDTH / (float)canvas.DISP_HEIGHT,  // aspectRatio
            1.0f,      // near clipping plane
            1000.0f ); // far clipping plane

        // create a light
        iLight = new Light();
        iLight.setColor(0xffffff);         // white light
        iLight.setIntensity(1.25f);          // overbright

        iLayerArr[0] = new GameLayer("/layer1.png", 0);
        iLayerArr[1] = new GameLayer("/layer2.png", 1);

        iBackground.setColor(0xffffcc); // set the background color
     }    
    /**
     * Paint the scene.
     */
    protected void paint(Graphics g) {

        // Bind the Graphics of this Canvas to our Graphics3D. The
        // viewport is automatically set to cover the entire clipping
        // rectangle of the Graphics object. The parameters indicate
        // that z-buffering, dithering, and true color rendering are
        // enabled, but antialiasing is disabled.
        iG3D.bindTarget(g, true,
                        Graphics3D.DITHER |
                        Graphics3D.TRUE_COLOR);

        // clear the color and depth buffers
        iG3D.clear(iBackground);

        // set up the camera in the desired position
        Transform transform = new Transform();
        transform.postTranslate(xOrigDisplay, yOrigDisplay, 30.0f);
        iG3D.setCamera(iCamera, transform);

        // set up a "headlight": a directional light shining
        // from the direction of the camera
        iG3D.resetLights();
        iG3D.addLight(iLight, transform);
        
        for(int i=0; i < iLayerArr.length; i++){
            iLayerArr[i].render(iG3D);
        }

        // flush
        iG3D.releaseTarget();
    }
    
    private void initStates(){
        stateArr[STATE_IDLE] = new StateIdle(this);
        //TODO: add more states here
        state = stateArr[STATE_IDLE];
    }

    void onTapScreen(int x, int y) {
        state.onTapScreen(x, y);
    }

    // 'isLast' parameter indicates whether this is the last point in the event sequention 
    void dragMapPosition(int xdelta, int ydelta, boolean isLast) {
        System.out.println("xdelta = " + xdelta + " ydelta = " + ydelta + " isLast = " + isLast);
        if(state.isAllowDragging()){
            xOrigDisplay -= (float)xdelta * panScale;
            yOrigDisplay += (float)ydelta * panScale;
        }
    }
    
    public void setState(int stateIdx){
        state = stateArr[stateIdx];
    }
    
}
